# -*- coding: utf-8 -*-
# @author : wanglei
# @date : 2020/5/13 3:00 PM
# @description :

from manimlib.imports import *
from from_victor.imports import *

"""
二阶行列式来历和计算规则
"""
class SecondOrderDeterminantOrigin(Scene):
    captions = [
        '行列式起初就是为了简化方程组解的表达方式',
        '对于这个二元一次方程组',
        '依据消元法，很容易得到它的解'
        '为了简化这种解的表达方式，人们定义了一种形式，两行两列的叫做二阶行列式',
        '它的计算规则就是对角线上的值相乘再相减，这样就简化了方程组解的表达方式',
    ]
    def construct(self):
        # 大括号
        fx = TexMobject('\\begin{cases}'
                         'a_{11}x_{1}+a_{12}x_{2}=b_{1} \\\ '
                         'a_{21}x_{1}+a_{22}x_{2}=b_{2} '
                         '\\end{cases}')
        fx[0][4:6].set_color(RED)
        fx[0][10:12].set_color(BLUE)
        fx[0][18:20].set_color(RED)
        fx[0][24:26].set_color(BLUE)
        fx.move_to(3*UP)
        self.play(Write(fx))
        self.wait(5)
        condition = TexMobject('\\text{解得：当}a_{11}a_{22}-a_{12}a_{21}\\neq0\\text{时}')
        condition.next_to(fx, 2*DOWN)
        x1 = TexMobject('x_{1}=\\frac{b_{1}a_{22}-a_{12}b_{2}}{a_{11}a_{22}-a_{12}a_{21}}')
        x1[0][0:2].set_color(RED)
        x2 = TexMobject('x_{2}=\\frac{a_{11}b_{2}-b_{1}a_{21}}{a_{11}a_{22}-a_{12}a_{21}}')
        x2[0][0:2].set_color(BLUE)
        x1.next_to(condition, 2*DOWN)
        x2.next_to(x1, 5*DOWN)
        self.play(Write(condition))
        self.play(Write(x1))
        self.play(Write(x2))
        self.wait(3)
        det_text = TexMobject('\\begin{vmatrix} '
                              'a_{11} &a_{12} \\\ '
                              'a_{21} &a_{22} \\\ '
                              '\\end{vmatrix}')
        det_text.next_to(x2, 2.5*DOWN)
        self.play(Write(det_text))
        self.wait(3)

        line = Line(det_text[0][4:7].get_center(), det_text[0][13:16].get_center(), color = YELLOW)
        self.play(ShowCreation(line))
        dashedLine = DashedLine(det_text[0][7:10].get_center(), det_text[0][10:13].get_center(), color = ORANGE)
        self.play(ShowCreation(dashedLine))
        gp = VGroup(det_text, line, dashedLine)
        self.play(ApplyMethod(gp.move_to, gp.get_center() + 2*LEFT))
        det_text_right = TexMobject(' = a_{11}a_{22}-a_{12}a_{21}')
        self.play(FadeInFromLarge(det_text_right.next_to(gp, RIGHT)))
        x1_denominator = x1[0][15:]
        x2_denominator = x2[0][15:]
        self.play(Indicate(x1_denominator), Indicate(x2_denominator), Indicate(det_text_right[0][1:]))
        x1_right = TexMobject('\\begin{vmatrix} '
                              'b_{1} &a_{12} \\\ '
                              'b_{2} &a_{22} \\\ '
                              '\\end{vmatrix}' ).scale(0.8)
        x1_right.move_to(x1[0][3:14].get_center() + 0.2 * UP)
        det_text_copy = det_text.copy().scale(0.8).move_to(x1_denominator.get_center() + 0.2 * DOWN)


        x2_right = TexMobject('\\begin{vmatrix} '
                              'a_{11} &b_{1} \\\ '
                              'a_{21} &b_{2} \\\ '
                              '\\end{vmatrix}').scale(0.8)
        x2_right.move_to(x2[0][3:14].get_center() + 0.2 * UP)
        det_text_copy2 = det_text.copy().scale(0.8).move_to(x2_denominator.get_center() + 0.2 * DOWN)

        self.play(Transform(x1[0][3:14], x1_right),
                  Transform(x1_denominator, det_text_copy),
                  Transform(x2[0][3:14], x2_right),
                  Transform(x2_denominator, det_text_copy2))
        self.wait(3)

"""
三阶行列式计算规则
"""
class ThreeOrderDeterminantComputer(Scene):
    captions = [
        '三阶行列式计算规则',
    ]
    def construct(self):
        det_text = TexMobject('\\begin{vmatrix} '
                              'a_{11} &a_{12} &a_{13} \\\ '
                              'a_{21} &a_{22} &a_{23} \\\ '
                              'a_{31} &a_{32} &a_{33} \\\ '
                              '\\end{vmatrix} \\\ ', color=WHITE)
        self.add(det_text)
        self.play(Write(det_text))
        all_det = []
        for i in range(6,33,3):
            all_det.append(det_text[0][i:i+3])
        """
        det_text[0][4:7] det_text[0][7:10] det_text[0][10:13]
        det_text[0][13:16]
        """
        p1 = Polygon(all_det[0].get_center(),
                     all_det[4].get_center(),
                     all_det[8].get_center(),
                     is_closed=False, stroke_opacity=0.4).set_color(BLUE)
        p2 = Polygon(all_det[1].get_center(),
                     all_det[5].get_center(),
                     all_det[-1].get_center() + 1 * RIGHT,
                     all_det[7].get_center() + 1.3 * RIGHT + 1.5 * DOWN,
                     all_det[6].get_center(),
                     is_closed=False, stroke_opacity=0.4).set_color(BLUE)
        p3 = Polygon(all_det[2].get_center(),
                     all_det[-1].get_center() + 1.7 * RIGHT + 0.3 * UP,
                     all_det[8].get_center() + RIGHT + DOWN,
                     all_det[7].get_center(),
                     all_det[3].get_center(),
                     is_closed=False, stroke_opacity=0.4).set_color(BLUE)

        self.play(ShowCreation(p1))
        self.play(ShowCreationThenFadeAround(all_det[0]), ShowCreationThenFadeAround(all_det[4]),
                  ShowCreationThenFadeAround(all_det[8]))
        self.play(ShowCreation(p2, run_time=2))
        self.play(ShowCreationThenFadeAround(all_det[1]), ShowCreationThenFadeAround(all_det[5]),
                  ShowCreationThenFadeAround(all_det[6]))
        self.play(ShowCreation(p3, run_time=2))
        self.play(ShowCreationThenFadeAround(all_det[2]), ShowCreationThenFadeAround(all_det[7]),
                  ShowCreationThenFadeAround(all_det[3]))

        p4 = Polygon(all_det[2].get_center(),
                     all_det[4].get_center(),
                     all_det[6].get_center(),
                     is_closed=False, stroke_opacity=0.4).set_color(RED)
        p5 = Polygon(all_det[1].get_center(),
                     all_det[3].get_center(),
                     all_det[-3].get_center() + 1 * LEFT,
                     all_det[7].get_center() + 1.3 * LEFT + 1.5 * DOWN,
                     all_det[8].get_center(),
                     is_closed=False, stroke_opacity=0.4).set_color(RED)
        p6 = Polygon(all_det[0].get_center(),
                     all_det[-3].get_center() + 1.7 * LEFT + 0.3 * UP,
                     all_det[6].get_center() + LEFT + DOWN,
                     all_det[7].get_center(),
                     all_det[5].get_center(),
                     is_closed=False, stroke_opacity=0.4).set_color(RED)
        self.play(ShowCreation(p4))
        self.play(ShowCreationThenFadeAround(all_det[2]), ShowCreationThenFadeAround(all_det[4]),
                  ShowCreationThenFadeAround(all_det[6]))
        self.play(ShowCreation(p5, run_time=2))
        self.play(ShowCreationThenFadeAround(all_det[1]), ShowCreationThenFadeAround(all_det[3]),
                  ShowCreationThenFadeAround(all_det[8]))
        self.play(ShowCreation(p6, run_time=2))
        self.play(ShowCreationThenFadeAround(all_det[0]), ShowCreationThenFadeAround(all_det[7]),
                  ShowCreationThenFadeAround(all_det[5]))

        gp = VGroup(*self.get_mobjects())
        self.play(ApplyMethod(gp.move_to, 3*UP))
        eq_tex =  TexMobject('= (a_{11}a_{22}a_{33}+a_{12}a_{23}a_{31}+a_{13}a_{32}a_{21}) \\\ '
                              '- (a_{13}a_{22}a_{31}+a_{12}a_{21}a_{33}+a_{11}a_{32}a_{33})').scale(0.9)
        self.play(Write(eq_tex, run_time=2))
        self.wait(2)


class determinantGeometricMeaning(Scene):
    '''
       行列式的几何意义【面积、体积】
       为什么向量积可表示为行列式？
       这是因为叉积和行列式都是 [公式] 中楔积（wedge product）的特殊形式
    '''
    CONFIG = {
        "x_min": 0,
        "x_max": 6,  # X坐标范围
        "x_tick_frequency": 1,  # X坐标刻度密度
        "x_labeled_nums": range(0, 7, 1),  # X坐标刻度数值
        "x_axis_label": "$x$",  # X坐标标注

        "y_min": 0,
        "y_max": 7,  # Y坐标范围
        "y_tick_frequency": 1,  # Y坐标刻度密度
        "y_labeled_nums": range(0, 8, 1),  # Y坐标刻度数值
        "y_axis_label": "$y$",  # Y坐标标注
        "exclude_zero_label": True,  # 不显示Y坐标的0刻度
        "x_axis_width": 6,
        "y_axis_height": 7,
        "graph_origin": ORIGIN,
        "camera_config": {"frame_center": -(2*LEFT + 2 * DOWN)},
    }
    captions=[
        '行列式的几何意义',
        '这里有一个二阶行列式',
        '那么行列式的值就是对角相乘再相减',
        '我们来看下这个值代表什么',
        '假设这个二阶行列式看做两个列向量',
        '得到这两个列向量组成的平行四边形',
        '然后我们画出外接矩形',
        '分别做垂线，获得每条边的长度',
        '然后标出每个形状的面积',
        '最大外接矩形的面积依次减掉每块的面积',
        '等于中间平行四边形的面积',
        '最后正好等于ad-bc',
        '所以可以得出结论：',
        '二阶行列式的值等于列向量乘积的值，也就是带方向的面积',
        '三阶行列式的值等于列向量乘积的值，也就是带方向的体积',
        '同理也能推广到高维度'
    ]

    def construct(self):
        # 一个二阶行列式
        det = TexMobject('\\begin{vmatrix} '
                              'a & b \\\ '
                              'c & d \\\ '
                              '\\end{vmatrix}')
        det[0][4].set_color(RED)
        det[0][5].set_color(BLUE)
        det[0][6].set_color(GREEN)
        det[0][7].set_color(YELLOW)
        det.move_to(self.camera_config['frame_center'])
        self.play(Write(det))
        self.wait(2)
        self.play(ApplyMethod(det.move_to, LEFT+self.camera_config['frame_center']))
        value = TextMobject('= ad - bc', tex_to_color_map={'a':RED, 'b':BLUE, 'c':GREEN, 'd':YELLOW})
        value.next_to(det, RIGHT)
        self.play(FadeInFromDown(value))
        self.wait(2)
        gp = VGroup(det, value)
        self.play(ApplyMethod(gp.move_to, gp.get_center()+6*UP))

        # 列向量
        v1 = Arrow(start=self.graph_origin, end=3 * RIGHT + 2 * UP, color=RED, stroke_width=3, buff=0)
        v1_matric = TexMobject('\\begin{bmatrix} a \\\ c \\end{bmatrix}', color=RED)
        v1_matric.next_to(v1.get_end(), TOP, aligned_edge=RIGHT, buff=0.1*SMALL_BUFF)
        v2 = Arrow(start=self.graph_origin, end=RIGHT + 3 * UP, color=BLUE, stroke_width=3, buff=0)
        v2_matric = TexMobject('\\begin{bmatrix} b \\\ d \\end{bmatrix}', color=BLUE)
        v2_matric.next_to(v2, RIGHT, aligned_edge=UP, buff=0.1*SMALL_BUFF)
        self.play(Write(v1), Write(v1_matric))
        self.play(Write(v2), Write(v2_matric))
        self.wait(2)
        # self.play(FadeOut(v1_matric), FadeOut(v2_matric))

        #平行四边形
        v2_copy = v2.copy()
        v1_copy = v1.copy()
        self.play(ApplyMethod(v2_copy.shift, v1.get_end() - self.graph_origin),
                  ApplyMethod(v1_copy.shift, v2.get_end() - self.graph_origin))
        self.wait(2)

        # 画长方形
        rectangle = Polygon(ORIGIN,
                       [0,5,0],
                       [4,5,0],
                       [4,0,0],
                       is_closed=True,
                       # stroke_opacity=0.4,
                       # fill_color=GRAY,
                       # fill_opacity=0.6)
                            )
        self.play(Write(rectangle))
        self.wait(2)

        # 向xy轴做垂线、标记长度
        v1_y = DashedLine(v1.get_end(), [3, 0, 0], color = GREEN) # c

        v2_x = DashedLine(v2.get_end(), [0, 3, 0], color = YELLOW)  # d

        self.play(Write(v1_y), Write(v2_x))

        # 向矩形的另外两条边做垂线、标记长度
        v1_right_x = DashedLine(v1.get_end(), [4, 2, 0], color = YELLOW) # d
        v2_top_y = DashedLine(v2.get_end(), [1, 5, 0], color = GREEN)  #  c

        self.play(Write(v1_right_x),  Write(v2_top_y))

        # 标出线段长度(从源点开始顺时针标)
        d = TextMobject('d', color=BLUE)
        d_l1 = Line(ORIGIN, [0,3,0])
        d_brace1 = Brace(d_l1, d_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=BLUE)
        d.next_to(d_brace1, LEFT)
        self.play(Write(d_brace1), Write(d))

        c = TextMobject('c', color=GREEN)
        c_l1 = Line([0,3,0], [0, 5, 0])
        c_brace1 = Brace(c_l1, c_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=GREEN)
        c.next_to(c_brace1, LEFT)
        self.play(Write(c_brace1), Write(c))

        b = TextMobject('b', color=YELLOW)
        b_l1 = Line([0, 5, 0], [1, 5, 0])
        b_brace1 = Brace(b_l1, b_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=YELLOW)
        b.next_to(b_brace1, TOP, buff=SMALL_BUFF/2)
        self.play(Write(b_brace1), Write(b))

        a = TextMobject('a', color=RED)
        a_l1 = Line([1, 5, 0], [4, 5, 0])
        a_brace1 = Brace(a_l1, a_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=RED)
        a.next_to(a_brace1, TOP, buff=SMALL_BUFF/2)
        self.play(Write(a_brace1), Write(a))

        d1 = TextMobject('d', color=BLUE)
        d1_l1 = Line([4, 5, 0], [4, 2, 0])
        d1_brace1 = Brace(d1_l1, d1_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=BLUE)
        d1.next_to(d1_brace1, RIGHT)
        self.play(Write(d1_brace1), Write(d1))

        c1 = TextMobject('c', color=GREEN)
        c1_l1 = Line([4, 2, 0], [4, 0, 0])
        c1_brace1 = Brace(c1_l1, c1_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=GREEN)
        c1.next_to(c1_brace1, RIGHT)
        self.play(Write(c1_brace1), Write(c1))

        b1 = TextMobject('b', color=YELLOW)
        b1_l1 = Line([4, 0, 0], [3, 0, 0])
        b1_brace1 = Brace(b1_l1, b1_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=YELLOW)
        b1.next_to(b1_brace1, BOTTOM, buff=SMALL_BUFF/2)
        self.play(Write(b1_brace1), Write(b1))

        a1 = TextMobject('a', color=RED)
        a1_l1 = Line([3, 0, 0], ORIGIN)
        a1_brace1 = Brace(a1_l1, a1_l1.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=RED)
        a1.next_to(a1_brace1, BOTTOM, buff=SMALL_BUFF/2)
        self.play(Write(a1_brace1), Write(a1))

        # 显示面积，并标记大小
        area1 = Polygon(ORIGIN,
                            [0, 3, 0],
                            v2.get_end(),
                            is_closed=True,
                            stroke_opacity=0.4,
                            fill_color=BLUE,
                            fill_opacity=0.6)
        area1_text = TexMobject('\\frac{bd}{2}').scale(0.7)
        area1_text.move_to(area1.get_center()+0.2*LEFT+0.05*TOP)
        self.play(Write(area1), Write(area1_text))

        area2 = Polygon([0, 3, 0],
                        [0, 5, 0],
                        [1, 5, 0],
                        v2.get_end(),
                        is_closed=True,
                        stroke_opacity=0.4,
                        fill_color=GREEN,
                        fill_opacity=0.6)
        area2_text = TexMobject('bc').scale(0.7)
        area2_text.move_to(area2.get_center())
        self.play(Write(area2), Write(area2_text))

        area3 = Polygon([1, 5, 0],
                        [4, 5, 0],
                        v2.get_end(),
                        is_closed=True,
                        stroke_opacity=0.4,
                        fill_color=RED,
                        fill_opacity=0.6)
        area3_text = TexMobject('\\frac{ac}{2}').scale(0.7)
        area3_text.move_to(area3.get_center()+0.2*LEFT+0.05*TOP)
        self.play(Write(area3), Write(area3_text))

        area4 = Polygon([4, 5, 0],
                        [4, 2, 0],
                        v1.get_end(),
                        is_closed=True,
                        stroke_opacity=0.4,
                        fill_color=BLUE,
                        fill_opacity=0.6)
        area4_text = TexMobject('\\frac{bd}{2}').scale(0.7)
        area4_text.move_to(area4.get_center()+0.2*RIGHT+0.05*BOTTOM)
        self.play(Write(area4), Write(area4_text))

        area5 = Polygon([4, 2, 0],
                        [4, 0, 0],
                        [3, 0, 0],
                        v1.get_end(),
                        is_closed=True,
                        stroke_opacity=0.4,
                        fill_color=GREEN,
                        fill_opacity=0.6)
        area5_text = TexMobject('bc').scale(0.7)
        area5_text.move_to(area5.get_center())
        self.play(Write(area5), Write(area5_text))

        area5 = Polygon([3, 0, 0],
                        ORIGIN,
                        v1.get_end(),
                        is_closed=True,
                        stroke_opacity=0.4,
                        fill_color=RED,
                        fill_opacity=0.6)
        area5_text = TexMobject('\\frac{ac}{2}').scale(0.7)
        area5_text.move_to(area5.get_center() + 0.2 * RIGHT + 0.05 * BOTTOM)
        self.play(Write(area5), Write(area5_text))


        # 显示结果
        # det_copy = det.copy().scale(0.6)
        # det_copy.move_to(3.5*LEFT + 0.6*BOTTOM + self.camera_config['frame_center'])
        # self.play(Write(det_copy))
        formula1 = TexMobject('(a+b)(d+c)-'
                              '(\\frac{bd}{2}+bc+\\frac{ac}{2}+\\frac{bd}{2}+bc+\\frac{ac}{2})').scale(0.7)
        # formula1.next_to(det_copy, RIGHT)
        formula1.move_to(0.6*BOTTOM + self.camera_config['frame_center'])
        formula2 = TexMobject('= (ad+ac+bd+bc)-(bd+2bc+ac)').scale(0.7)
        formula2.next_to(formula1, BOTTOM, buff=0.1*SMALL_BUFF, aligned_edge=LEFT)
        self.play(Write(formula1), run_time=3)
        self.wait()
        self.play(Write(formula2))
        value_copy = value.copy().scale(0.7)
        value_copy.next_to(formula2, BOTTOM, buff=0.1*SMALL_BUFF, aligned_edge=LEFT)
        self.play(Write(value_copy))
        self.wait(2)

class determinantGeometricMeaning2(Scene):
    '''
    行列式的几何意义
    '''
    def construct(self):
        result1 = TexMobject('\\text{所以可以得出结论：}')
        result1.scale(0.5)
        result2 = TexMobject('\\text{二阶行列式的值等于列向量乘积的值，也就是带方向的面积}')
        result2.scale(0.5)
        result2.next_to(result1, BOTTOM, buff=0.5*SMALL_BUFF)
        result3 = TexMobject('\\text{三阶行列式的值等于列向量乘积的值，也就是带方向的体积}')
        result3.scale(0.5)
        result3.next_to(result2, BOTTOM, buff=0.5*SMALL_BUFF)
        result4 = TexMobject('\\text{同理也能推广到高维度}')
        result4.scale(0.5)
        result4.next_to(result3, BOTTOM, buff=0.5*SMALL_BUFF, aligned_edge=LEFT)
        self.play(Write(result1), run_time=2)
        self.play(Write(result2), run_time=3)
        self.play(Write(result3), run_time=3)
        self.play(Write(result4), run_time=2)
        self.wait(4)
